package gw

import (
	"image"
	"image/color"
	"log"
	"time"

	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/widget/material"
)

// Prompt is a modal dialog that prompts the user for a response.
type ModelType byte

const (
	ModalInfo  ModelType = 0
	ModalWarn  ModelType = 1
	ModalError ModelType = 2
)

const (
	IconPositionStart = 0
	IconPositionEnd   = 1
)

var (
	colors = map[ModelType]color.NRGBA{
		// Red
		ModalError: {R: 0xD1, G: 0x1E, B: 0x35, A: 0xFF},
		// Light blue
		ModalInfo: {R: 250, G: 250, B: 250, A: 0xFF},
		// Yellow
		ModalWarn: {R: 0xFD, G: 0xB5, B: 0x0E, A: 0xFF},
	}
)

type MessageBox struct {
	Title   string
	Message string
	Type    ModelType
	Visible bool

	Widget[MessageBox]
	lastWidth    int
	rememberBool *widget.Bool

	options     []MBOption
	result      string
	needRefresh bool

	onSubmit func(selectedOption string, remember bool)

	content Contenter
}

type MBOption struct {
	Text   string
	Button widget.Clickable
	Icon   *widget.Icon
}

func NewMessage(win *Window, title, content string, modalType ModelType, options ...MBOption) *MessageBox {
	m := &MessageBox{
		Title:   title,
		Message: content,
		Type:    modalType,
		options: options,
	}
	m.Init(win, m)
	m.MaxWidth = 400
	m.lastWidth = m.MaxWidth
	m.MaxHeight = 200
	m.win = win
	return m
}
func (m *MessageBox) RestoreWidth() *MessageBox {
	m.MaxWidth = m.lastWidth
	return m
}

func (p *MessageBox) SetOptions(options ...MBOption) {
	p.options = options
}

func (p *MessageBox) Show() {
	p.Visible = true
	p.needRefresh = true
}

func (p *MessageBox) Hide() {
	p.Visible = false
}

func (p *MessageBox) IsVisible() bool {
	return p.Visible
}

func (p *MessageBox) WithRememberBool() {
	p.rememberBool = &widget.Bool{Value: false}
}

func (p *MessageBox) WithoutRememberBool() {
	p.rememberBool = nil
}

func (p *MessageBox) SetOnSubmit(f func(selectedOption string, remember bool)) {
	p.onSubmit = f
}

func (p *MessageBox) submit() {
	if p.onSubmit == nil {
		return
	}

	if !p.Visible {
		return
	}

	if p.rememberBool == nil {
		p.onSubmit(p.result, false)
		return
	}

	p.onSubmit(p.result, p.rememberBool.Value)
}

func (p *MessageBox) Result() (string, bool) {
	if p.result == "" {
		return "", false
	}

	if p.rememberBool != nil {
		return p.result, p.rememberBool.Value
	}

	return p.result, false
}

func (p *MessageBox) Layout(gtx layout.Context) layout.Dimensions {
	if !p.Visible {
		return layout.Dimensions{}
	}

	textColor := p.Theme().ContrastFg
	switch p.Type {
	case ModalInfo:
		textColor = color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}
	case ModalWarn:
		textColor = color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}
	case ModalError:
		textColor = color.NRGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}
	}

	border := widget.Border{
		Color:        Border,
		Width:        2,
		CornerRadius: 2,
	}
	return border.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
		return layout.Background{}.Layout(gtx,
			func(gtx layout.Context) layout.Dimensions {
				defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, 8).Push(gtx.Ops).Pop()
				paint.Fill(gtx.Ops, colors[p.Type])
				return layout.Dimensions{Size: gtx.Constraints.Min}
			}, func(gtx layout.Context) layout.Dimensions {
				return layout.UniformInset(unit.Dp(10)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
					return layout.Flex{
						Axis:      layout.Vertical,
						Alignment: layout.Middle,
					}.Layout(gtx,
						layout.Rigid(func(gtx layout.Context) layout.Dimensions {
							return layout.Inset{Bottom: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
								h := material.H6(p.Theme(), p.Title)
								h.Color = textColor
								return h.Layout(gtx)
							})
						}),
						layout.Rigid(func(gtx layout.Context) layout.Dimensions {
							return layout.Inset{Bottom: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
								var d layout.Dimensions
								dp := gtx.Dp(110)
								if p.content != nil {
									//替换为自定义容器
									d = p.content.Layout(gtx)
									if p.win.height-d.Size.Y < dp {
										d.Size.Y = p.win.height - dp
									}
								} else {
									b := material.Body1(p.Theme(), p.Message)
									b.Color = textColor
									d = b.Layout(gtx)
								}
								p.MaxHeight = d.Size.Y + dp
								if p.needRefresh {
									log.Println(p.MaxHeight)
									p.needRefresh = false
									gtx.Execute(op.InvalidateCmd{At: gtx.Now.Add(time.Second / 100)})
								}
								return d
							})
						}),

						layout.Rigid(func(gtx layout.Context) layout.Dimensions {
							ops := p.options
							count := len(ops)
							if p.rememberBool != nil {
								count++
							}

							items := make([]layout.FlexChild, 0, count)
							if p.rememberBool != nil {
								items = append(
									items,
									layout.Rigid(func(gtx layout.Context) layout.Dimensions {
										return material.CheckBox(p.Theme(), p.rememberBool, "Don't ask again").Layout(gtx)
									}),
									layout.Rigid(layout.Spacer{Width: unit.Dp(4)}.Layout),
								)
							}

							for i := range ops {
								i := i

								if ops[i].Button.Clicked(gtx) {
									p.result = ops[i].Text
									p.submit()
								}

								items = append(
									items,
									layout.Rigid(func(gtx layout.Context) layout.Dimensions {
										gtx.Constraints.Max.Y = gtx.Dp(40)
										btn := material.Button(p.Theme(), &ops[i].Button, ops[i].Text)
										btn.Inset = layout.Inset{
											Top: 5, Bottom: 5,
											Left: 12, Right: 12,
										}
										return btn.Layout(gtx)
										//return material.Button(p.Theme(), &p.options[i].Button, p.options[i].Text).Layout(gtx)
									}),
									layout.Rigid(layout.Spacer{Width: unit.Dp(4)}.Layout),
								)
							}
							return layout.Inset{Top: unit.Dp(5)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
								return layout.Flex{
									Axis:      layout.Horizontal,
									Alignment: layout.Middle,
									Spacing:   layout.SpaceStart,
								}.Layout(gtx,
									items...,
								)
							})
						}),
					)
				})

			},
		)
	})

}
